package room

import (
	"errors"
	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) checkProduceReqData(data common.SFUStartProduceReqData) error {
	// Check if transport ID is provided
	if data.TransportId == "" {
		return errors.New("transport ID is required in produce request")
	}

	// Check if room ID is provided
	if data.RoomId == "" {
		return errors.New("room ID is required in produce request")
	}

	// Check if user ID is provided
	if data.UserId == "" {
		return errors.New("user ID is required in produce request")
	}

	// Check media information
	if err := ValidateMediaInfo(data.Media); err != nil {
		return errors.New("invalid media information in produce request: " + err.Error())
	}

	// Check if rtp parameters are provided
	if data.RtpParameters == nil {
		return errors.New("RTP parameters are required in produce request")
	}

	// Check if room exists
	if !s.roomMgr.RoomExists(data.RoomId) {
		return errors.New("room does not exist")
	}

	// Check if user exists in the room
	if !s.roomMgr.UserExists(data.RoomId, data.UserId) {
		return errors.New("user does not exist in the room")
	}

	// Check if transport exists
	if !s.roomMgr.SendTransportExists(data.RoomId, data.UserId) {
		return errors.New("transport does not exist in the room")
	}

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) sendStartProduceResponse(rid string, code int, msg string,
	data common.SFUStartProduceReqData, producerId string, connId string) {
	resMsg := common.Message{
		Cmd: common.SFU_START_PRODUCE_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: code,
			Msg:  msg,
			Data: common.SFUStartProduceResData{
				RoomId:     data.RoomId,
				UserId:     data.UserId,
				Media:      data.Media,
				ProducerId: producerId,
			},
		},
	}

	s.dispatcher.Dispatch(resMsg, s.serviceInfo, common.AccessServiceInfo, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) handleStartProduceReq(msg common.Message, from common.ServiceInfo,
	connId string) error {
	LOG().WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("Handling SFU Produce Request")

	dataMap, ok := msg.Data.(map[string]interface{})
	if !ok {
		return errors.New("invalid data format in produce request")
	}

	var data common.SFUStartProduceReqData
	if err := mapstructure.Decode(dataMap, &data); err != nil {
		return errors.New("failed to decode produce request data: " + err.Error())
	}

	if err := s.checkProduceReqData(data); err != nil {
		LOG().WithError(err).Error("produce request validation failed")
		s.sendStartProduceResponse(msg.Rid, 1, err.Error(), data, "", connId)
		return nil
	}

	producer, err := s.roomMgr.CreateProducer(msg.Rid, data)
	if err != nil {
		LOG().WithError(err).Error("failed to create producer")
		s.sendStartProduceResponse(msg.Rid, 1, err.Error(), data, "", connId)
		return nil
	}

	LOG().WithFields(logrus.Fields{
		"producer_id": producer.ProducerId,
	}).Info("Producer created successfully")

	s.sendStartProduceResponse(msg.Rid, 0, "success", data, producer.ProducerId, connId)

	return nil
}
